#ifndef HEAD_H
#define HEAD_H

#define NULL 0
#define NUM_OPEN 20 
#define NUM_TASKS 64
#define FIRST_TSS_ENTRY 4
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
#define MOVE_TO_USER_MODE() \
__asm__ (\
         "pushl $0x17 \n\t"\
         "pushl %%esp \n\t"\
         "pushfl \n\t"\
         "pushl $0x0f \n\t"\
         "pushl $1f \n\t"\
         "iret \n\t"\
         "1: \t movl $0x17, %%eax \n\t"\
         "movw %%ax, %%ds \n\t"\
         "movw %%ax, %%es \n\t"\
         "movw %%ax, %%gs \n\t"\
         "movw %%ax, %%fs \n\t"\
         :::"ax")
#define TSS(n) ((((unsigned int) n)<<4)+(FIRST_TSS_ENTRY<<3))
#define LDT(n) ((((unsigned int) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define LTR(n) __asm__("ltr %%ax"::"a"(TSS(n)))
#define LLDT(n) __asm__("lldt %%ax"::"a"(LDT(n)))
#define CLEARNT() __asm__("pushfl; andl $0xffffbfff,(%esp); popfl")
#define SET_DESC_LOW32(addr)\
   (0x68 + ((addr&0xffff)<<16)) 
#define SET_DESC_HIGH32(addr, type)\
    (((addr&0xff000000)<<24) + (type<<8) + ((addr&0x00ff0000)>>16))

struct desc_struct {
    unsigned int a;
    unsigned int b;
};

struct tss_struct{
    unsigned int back_link;
    unsigned int esp0;
    unsigned int ss0;
    unsigned int esp1;
    unsigned int ss1;
    unsigned int esp2;
    unsigned int ss2;
    unsigned int cr3;
    unsigned int eip;
    unsigned int eflags;
    unsigned int eax;
    unsigned int ecx;
    unsigned int edx;
    unsigned int ebx;
    unsigned int esp;
    unsigned int ebp;
    unsigned int esi;
    unsigned int edi;
    unsigned int es;
    unsigned int cs;
    unsigned int ss;
    unsigned int ds;
    unsigned int fs;
    unsigned int gs;
    unsigned int ldt_selector;
    unsigned int map_address; 
};

struct inode{
    unsigned short i_mode;
    unsigned short i_uid;
    unsigned int i_size;
    unsigned int i_mtime;
    unsigned int i_gid;
    unsigned int i_nlinks;
    unsigned short i_zone[9];
    struct task_struct *i_wait;
    unsigned int i_atime;
    unsigned int i_ctime;
    unsigned int i_dev;
    unsigned int i_num;
    unsigned int i_count;
    unsigned char i_lock;
    unsigned char i_dirt; 
    unsigned char i_pipe;
    unsigned char i_mount;
    unsigned char i_seek;
    unsigned char i_update;
};

struct file{
    unsigned short f_mode;
    unsigned short f_flags;
    unsigned short f_count;
    struct inode_struct *f_inode;
    unsigned int f_pos;
};


struct task_struct{
    /* hardcode 
    unsigned int state;
    unsigned int counter;
    unsigned int priority;
    unsigned int signal;
    unsigned int blocked;*/
    /* various field 
    int exit_code;
    unsigned int start_code, end_code, brk, start_stack;
    unsigned int pid, gid;
    unsigned int alarm;*/
    /* file info
    unsigned int tty;
    unsigned int umask;
    struct inode_struct *pwd;
    struct inode_struct *root;
    struct inode_struct *executable;
    unsigned int close_on_exec;
    struct file * filep[NUM_OPEN];*/
    /* ldt for task, 0:zero, 1:cs, 2:ds&ss */
    struct desc_struct ldt[3];
    /* tss for task */
    struct tss_struct tss;
};

void schedule_init();



#endif
